import { useState, useEffect } from "react";

/**
 * useForm ,form bindTo data,and validation
 * //formData.$$change: the form if had change
 * //formData.$$valid: the form if is valid
 * @param  {Function} callback   [description]
 * @param  {Object}   inintValue [description]
 * @param  {string}   formName [description]
 * @return {object}              [description]
 * @constructor useForm
 * @example
 const {
        formData,
        handleChange,
        handleSubmit,
        updateFormData,
        validations,
        addValidate,
        addValidateMulti
    } = useForm(doSubmit, {}, "testForm");

 

 function doSubmit() {
     console.log(formData);
 }

 function validate1(value) {
     console.log(value);
     return value.length > 2 ? "" : "长度小于2";
 }

 // addValidate("test1", [validate1]);
    addValidateMulti({ test1: [validate1] });   

 return (
    <>
        <form name="testForm" onSubmit={handleSubmit}>
            <input
                className="input"
                type="email"
                name="email"
                onChange={handleChange}
                value={formData.email}
                required
            />
            <input
                className={formData.$$status.test1 ? "a" : "b"}
                type="text"
                name="test1"
                onChange={handleChange}
                value={formData.test1}
            />
            <input
                className="input"
                type="password"
                name="password"
                onChange={handleChange}
                value={formData.password}
                required
            />
            <select
                name="level"
                onChange={handleChange}
                value={formData.level}
            >
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
                <option value="4">4</option>
                <option value="5">5</option>
            </select>
            <button>提交</button>
        </form>
    </>
 );

 */
export default function useForm(callback, inintValue = {}, formName) {
    console.log("load useForm.js", formData);
    inintValue.$$status = {};
    inintValue.$$change = false;
    const [formData, __updateFormData] = useState(inintValue);
    const validations = {};
    // formData["$$status"] = {};
    const handleSubmit = event => {
        if (event) event.preventDefault();
        callback && callback();
    };

    //addValidate('test1',[func1,func2,func3]);
    function addValidate(name, vList) {
        if (Uts.notEmptyString(name) && Uts.notEmptyArray(vList)) {
            validations[name] = validations[name] || [];
            Uts.mergeArray(validations[name], vList);
        }
    }

    //addValidateMulti({test1:[func1,func2,func3],test2:[func1,func2]});
    function addValidateMulti(options) {
        if (Uts.isObject(options)) {
            for (let vConfig in options) {
                addValidate(vConfig, options[vConfig]);
            }
        }
    }

    function __checkAndSetFormIfValid(ifNotInit) {
        //loop for opt except $$status,$$change,$$valid
        if (formName) {
            if (document.forms[formName].checkValidity) {
                if (!document.forms[formName].checkValidity()) {
                    formData.$$valid = false;
                    if (!ifNotInit) {
                        //update $valid when init form status
                        updateFormData(formData);
                    }
                    return false;
                }
            }
            if (ifNotInit) {
                let elementArr = document.forms[formName].elements;
                if (elementArr.length) {
                    for (var i = elementArr.length - 1; i >= 0; i--) {
                        let currentEle = elementArr[i];
                        if (
                            currentEle.name &&
                            !_checkCurrentValueWithValidations(
                                currentEle.name,
                                currentEle.value
                            )
                        ) {
                            formData.$$valid = false;
                            return false;
                        }
                    }
                }
            }
            formData.$$valid = true;
            return true;
        }
    }

    function updateFormData(data) {
        let value = { ...formData, ...data };
        __updateFormData(function(values) {
            return value;
        });
    }

    function _checkCurrentValueWithValidations(name, value) {
        let isValid = true;
        Uts.each(validations[name], function(fc, index) {
            let currentResult = fc(value);
            if (currentResult) {
                isValid = false;
            }
        });
        return isValid;
    }

    const handleChange = event => {
        event.persist && event.persist();
        if (!Uts.isDefined(formData["$$valid"])) {
            formData["$$valid"] = true;
        }
        if (!formData.$$change) {
            formData.$$change = true;
        }
        let currentValue = event.target.value;
        formData[event.target.name] = currentValue;
        if (event.target.checkValidity) {
            if (!event.target.checkValidity()) {
                formData["$$status"][event.target.name] = "格式不正确";
                formData["$$valid"] = false;
                updateFormData(formData);
                return;
            } else {
                formData["$$status"][event.target.name] = "";
                // formData["$$valid"] = false;
            }
        }
        let currentValidateMethods = validations[event.target.name];
        if (currentValidateMethods) {
            let validResult = "";
            Uts.each(currentValidateMethods, function(fc, index) {
                let currentResult = fc(currentValue);
                if (currentResult) {
                    validResult += validResult
                        ? "；" + currentResult
                        : currentResult;
                }
            });
            formData["$$status"][event.target.name] = validResult;
        }
        __checkAndSetFormIfValid(true);
        // __updateFormData(formData);
        __updateFormData(function(formData) {
            // return formData;
            return {
                ...formData,
                // $$status: formData["$$status"],
                [event.target.name]: currentValue
            };
        });
    };

    React.useEffect(() => {
        __checkAndSetFormIfValid();
    }, []);

    return {
        handleChange,
        handleSubmit,
        formData,
        updateFormData,
        validations,
        addValidate,
        addValidateMulti
    };
}
